package org.jflame.auth;

import org.jflame.auth.authz.Permit;
import org.jflame.commons.util.ArrayHelper;
import org.jflame.commons.util.CollectionHelper;

import java.beans.Transient;
import java.io.Serializable;
import java.util.Set;

/**
 * 已验证的登录用户信息
 * 
 * @author charles.zhang
 */
public abstract class LoginUser implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 用户id
     * 
     * @return
     */
    public abstract String getId();

    /**
     * 用户名
     * 
     * @return
     */
    public abstract String getUserName();

    /**
     * 用户角色
     * 
     * @return
     */
    public abstract Set<String> getRoles();

    /**
     * 用户权限集
     * 
     * @return
     */
    public abstract Set<Permit> getPermits();

    /**
     * 用户附属性信息
     * 
     * @param <T>
     * @return
     */
    public <T extends Serializable> T getUserDetail() {
        return null;
    }

    /**
     * 判断用户是否有指定权限
     * 
     * @param p 要访问的权限资源
     * @return
     */
    @Transient
    public final boolean isPermitted(Permit p) {
        Set<Permit> permits = getPermits();
        if (CollectionHelper.isEmpty(permits)) {
            return false;
        }
        for (Permit permit : permits) {
            if (permit.implies(p)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断用户是否其中任意一个资源的权限
     * 
     * @param _permits
     * @return
     */
    public final boolean isAnyPermitted(Permit... _permits) {
        Set<Permit> permits = getPermits();
        if (CollectionHelper.isEmpty(permits)) {
            return false;
        }
        for (Permit permit : permits) {
            for (Permit p : _permits) {
                if (permit.implies(p)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 判断用户是否有指定角色
     * 
     * @param roleCode 角色标识
     * @return
     */
    public final boolean hasRole(String roleCode) {
        Set<String> roles = getRoles();
        return CollectionHelper.isNotEmpty(roles) && roles.stream()
                .anyMatch(p -> p.equals(roleCode));
    }

    public final boolean hasAnyRole(String... roleCodes) {
        Set<String> roles = getRoles();
        return CollectionHelper.isNotEmpty(roles) && roles.stream()
                .anyMatch(p -> ArrayHelper.contains(roleCodes, p));
    }
}
